{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Execute this cell to install dependencies\n",
    "%pip install sf-hamilton[visualization]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example of using with_columns for Pandas [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/dagworks-inc/hamilton/blob/main/examples/pandas/with_columns/notebook.ipynb) [![GitHub badge](https://img.shields.io/badge/github-view_source-2b3137?logo=github)](https://github.com/apache/hamilton/blob/main/examples/pandas/with_columns/notebook.ipynb)\n",
    "\n",
    "This allows you to efficiently run groups of map operations on a dataframe.\n",
    "Here's an example of calling it -- if you've seen `@subdag`, you should be familiar with the concepts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/jernejfrank/miniconda3/envs/hamilton/lib/python3.10/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "%reload_ext hamilton.plugins.jupyter_magic\n",
    "from hamilton import driver\n",
    "import my_functions\n",
    "\n",
    "my_builder = driver.Builder().with_modules(my_functions).with_config({\"case\":\"thousands\"})\n",
    "output_node = [\"final_df\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.1.2 (20240928.0832)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"1323pt\" height=\"422pt\"\n",
       " viewBox=\"0.00 0.00 1322.70 422.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 418)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-418 1318.7,-418 1318.7,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-222 8,-406 92.85,-406 92.85,-222 8,-222\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-388.7\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- case -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>case</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"83.55,-130 11.3,-130 11.3,-80 89.55,-80 89.55,-124 83.55,-130\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"83.55,-130 83.55,-124\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"89.55,-124 83.55,-124\"/>\n",
       "<text text-anchor=\"start\" x=\"35.42\" y=\"-113.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">case</text>\n",
       "<text text-anchor=\"start\" x=\"19.3\" y=\"-85.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">thousands</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>final_df.spend_zero_mean</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M703.15,-151.8C703.15,-151.8 535.3,-151.8 535.3,-151.8 529.3,-151.8 523.3,-145.8 523.3,-139.8 523.3,-139.8 523.3,-100.2 523.3,-100.2 523.3,-94.2 529.3,-88.2 535.3,-88.2 535.3,-88.2 703.15,-88.2 703.15,-88.2 709.15,-88.2 715.15,-94.2 715.15,-100.2 715.15,-100.2 715.15,-139.8 715.15,-139.8 715.15,-145.8 709.15,-151.8 703.15,-151.8\"/>\n",
       "<text text-anchor=\"start\" x=\"534.1\" y=\"-128.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_zero_mean</text>\n",
       "<text text-anchor=\"start\" x=\"600.1\" y=\"-100.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1018.5,-181.8C1018.5,-181.8 756.15,-181.8 756.15,-181.8 750.15,-181.8 744.15,-175.8 744.15,-169.8 744.15,-169.8 744.15,-130.2 744.15,-130.2 744.15,-124.2 750.15,-118.2 756.15,-118.2 756.15,-118.2 1018.5,-118.2 1018.5,-118.2 1024.5,-118.2 1030.5,-124.2 1030.5,-130.2 1030.5,-130.2 1030.5,-169.8 1030.5,-169.8 1030.5,-175.8 1024.5,-181.8 1018.5,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"754.95\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_zero_mean_unit_variance</text>\n",
       "<text text-anchor=\"start\" x=\"868.2\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean&#45;&gt;final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>final_df.spend_zero_mean&#45;&gt;final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M715.54,-130.75C721.18,-131.38 726.91,-132.03 732.69,-132.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"732.04,-136.13 742.37,-133.77 732.83,-129.17 732.04,-136.13\"/>\n",
       "</g>\n",
       "<!-- final_df -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>final_df</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1302.7,-181.8C1302.7,-181.8 1236.85,-181.8 1236.85,-181.8 1230.85,-181.8 1224.85,-175.8 1224.85,-169.8 1224.85,-169.8 1224.85,-130.2 1224.85,-130.2 1224.85,-124.2 1230.85,-118.2 1236.85,-118.2 1236.85,-118.2 1302.7,-118.2 1302.7,-118.2 1308.7,-118.2 1314.7,-124.2 1314.7,-130.2 1314.7,-130.2 1314.7,-169.8 1314.7,-169.8 1314.7,-175.8 1308.7,-181.8 1302.7,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"1245.78\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df</text>\n",
       "<text text-anchor=\"start\" x=\"1235.65\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- final_df.spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>final_df.spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M231.45,-211.8C231.45,-211.8 142.35,-211.8 142.35,-211.8 136.35,-211.8 130.35,-205.8 130.35,-199.8 130.35,-199.8 130.35,-160.2 130.35,-160.2 130.35,-154.2 136.35,-148.2 142.35,-148.2 142.35,-148.2 231.45,-148.2 231.45,-148.2 237.45,-148.2 243.45,-154.2 243.45,-160.2 243.45,-160.2 243.45,-199.8 243.45,-199.8 243.45,-205.8 237.45,-211.8 231.45,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"141.15\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend</text>\n",
       "<text text-anchor=\"start\" x=\"167.77\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_zero_mean -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_zero_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.75,-150.87C254.98,-146.12 266.89,-141.84 278.45,-139 355.09,-120.2 444.25,-115.85 512,-115.98\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"511.58,-119.48 521.6,-116.04 511.62,-112.48 511.58,-119.48\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_per_signup -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>final_df.spend_per_signup</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M471.05,-375.8C471.05,-375.8 301.7,-375.8 301.7,-375.8 295.7,-375.8 289.7,-369.8 289.7,-363.8 289.7,-363.8 289.7,-324.2 289.7,-324.2 289.7,-318.2 295.7,-312.2 301.7,-312.2 301.7,-312.2 471.05,-312.2 471.05,-312.2 477.05,-312.2 483.05,-318.2 483.05,-324.2 483.05,-324.2 483.05,-363.8 483.05,-363.8 483.05,-369.8 477.05,-375.8 471.05,-375.8\"/>\n",
       "<text text-anchor=\"start\" x=\"300.5\" y=\"-352.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_per_signup</text>\n",
       "<text text-anchor=\"start\" x=\"367.25\" y=\"-324.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_per_signup -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_per_signup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M212.38,-212.17C223.75,-227.23 237.39,-245.46 249.45,-262 262.6,-280.04 260.83,-289.3 278.45,-303 279.58,-303.87 280.72,-304.73 281.89,-305.57\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"279.62,-308.27 289.89,-310.87 283.49,-302.43 279.62,-308.27\"/>\n",
       "</g>\n",
       "<!-- final_df.avg_3wk_spend -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>final_df.avg_3wk_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M482.3,-293.8C482.3,-293.8 290.45,-293.8 290.45,-293.8 284.45,-293.8 278.45,-287.8 278.45,-281.8 278.45,-281.8 278.45,-242.2 278.45,-242.2 278.45,-236.2 284.45,-230.2 290.45,-230.2 290.45,-230.2 482.3,-230.2 482.3,-230.2 488.3,-230.2 494.3,-236.2 494.3,-242.2 494.3,-242.2 494.3,-281.8 494.3,-281.8 494.3,-287.8 488.3,-293.8 482.3,-293.8\"/>\n",
       "<text text-anchor=\"start\" x=\"289.25\" y=\"-270.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.avg_3wk_spend: case</text>\n",
       "<text text-anchor=\"start\" x=\"367.25\" y=\"-242.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.avg_3wk_spend -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.avg_3wk_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.71,-205.89C255.14,-211.02 267.14,-216.28 278.45,-221 282.04,-222.5 285.72,-224.01 289.43,-225.52\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"288,-228.72 298.58,-229.21 290.61,-222.23 288,-228.72\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_mean -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>final_df.spend_mean</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M452.68,-91.8C452.68,-91.8 320.07,-91.8 320.07,-91.8 314.07,-91.8 308.07,-85.8 308.07,-79.8 308.07,-79.8 308.07,-40.2 308.07,-40.2 308.07,-34.2 314.07,-28.2 320.07,-28.2 320.07,-28.2 452.68,-28.2 452.68,-28.2 458.68,-28.2 464.68,-34.2 464.68,-40.2 464.68,-40.2 464.68,-79.8 464.68,-79.8 464.68,-85.8 458.68,-91.8 452.68,-91.8\"/>\n",
       "<text text-anchor=\"start\" x=\"318.88\" y=\"-68.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_mean</text>\n",
       "<text text-anchor=\"start\" x=\"373.62\" y=\"-40.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">float</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_mean -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M222.31,-148.04C238.55,-134 258.67,-118.01 278.45,-106 284.66,-102.23 291.23,-98.61 297.95,-95.18\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"299.08,-98.52 306.5,-90.95 295.98,-92.24 299.08,-98.52\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_std_dev -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>final_df.spend_std_dev</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M460.18,-211.8C460.18,-211.8 312.57,-211.8 312.57,-211.8 306.57,-211.8 300.57,-205.8 300.57,-199.8 300.57,-199.8 300.57,-160.2 300.57,-160.2 300.57,-154.2 306.57,-148.2 312.57,-148.2 312.57,-148.2 460.18,-148.2 460.18,-148.2 466.18,-148.2 472.18,-154.2 472.18,-160.2 472.18,-160.2 472.18,-199.8 472.18,-199.8 472.18,-205.8 466.18,-211.8 460.18,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"311.38\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_std_dev</text>\n",
       "<text text-anchor=\"start\" x=\"373.62\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">float</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_std_dev -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_std_dev</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.7,-180C257.83,-180 273.42,-180 288.94,-180\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"288.69,-183.5 298.69,-180 288.69,-176.5 288.69,-183.5\"/>\n",
       "</g>\n",
       "<!-- final_df.__append -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>final_df.__append</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1183.85,-181.8C1183.85,-181.8 1071.5,-181.8 1071.5,-181.8 1065.5,-181.8 1059.5,-175.8 1059.5,-169.8 1059.5,-169.8 1059.5,-130.2 1059.5,-130.2 1059.5,-124.2 1065.5,-118.2 1071.5,-118.2 1071.5,-118.2 1183.85,-118.2 1183.85,-118.2 1189.85,-118.2 1195.85,-124.2 1195.85,-130.2 1195.85,-130.2 1195.85,-169.8 1195.85,-169.8 1195.85,-175.8 1189.85,-181.8 1183.85,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"1070.3\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.__append</text>\n",
       "<text text-anchor=\"start\" x=\"1093.55\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- final_df.spend_per_signup&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>final_df.spend_per_signup&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M483.43,-345.54C524.91,-345.8 573.97,-345.59 618.23,-344\"/>\n",
       "</g>\n",
       "<!-- final_df.avg_3wk_spend&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>final_df.avg_3wk_spend&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M471.59,-294.24C531.09,-316.62 602.89,-342.66 618.23,-344\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M620.23,-344C795.12,-359.28 983.91,-249.39 1073.58,-188.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1075.46,-191.51 1081.73,-182.96 1071.5,-185.73 1075.46,-191.51\"/>\n",
       "</g>\n",
       "<!-- final_df.__append&#45;&gt;final_df -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>final_df.__append&#45;&gt;final_df</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M1196.26,-150C1202,-150 1207.75,-150 1213.38,-150\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1213.17,-153.5 1223.17,-150 1213.17,-146.5 1213.17,-153.5\"/>\n",
       "</g>\n",
       "<!-- final_df.signups -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>final_df.signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M237.45,-334.8C237.45,-334.8 136.35,-334.8 136.35,-334.8 130.35,-334.8 124.35,-328.8 124.35,-322.8 124.35,-322.8 124.35,-283.2 124.35,-283.2 124.35,-277.2 130.35,-271.2 136.35,-271.2 136.35,-271.2 237.45,-271.2 237.45,-271.2 243.45,-271.2 249.45,-277.2 249.45,-283.2 249.45,-283.2 249.45,-322.8 249.45,-322.8 249.45,-328.8 243.45,-334.8 237.45,-334.8\"/>\n",
       "<text text-anchor=\"start\" x=\"135.15\" y=\"-311.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.signups</text>\n",
       "<text text-anchor=\"start\" x=\"167.77\" y=\"-283.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.signups&#45;&gt;final_df.spend_per_signup -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>final_df.signups&#45;&gt;final_df.spend_per_signup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.84,-315.86C258.96,-317.75 268.57,-319.75 278.29,-321.77\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"277.31,-325.14 287.81,-323.74 278.73,-318.28 277.31,-325.14\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean_unit_variance&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>final_df.spend_zero_mean_unit_variance&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M1030.76,-150C1036.54,-150 1042.25,-150 1047.83,-150\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1047.55,-153.5 1057.55,-150 1047.55,-146.5 1047.55,-153.5\"/>\n",
       "</g>\n",
       "<!-- initial_df -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>initial_df</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-211.8C83.35,-211.8 17.5,-211.8 17.5,-211.8 11.5,-211.8 5.5,-205.8 5.5,-199.8 5.5,-199.8 5.5,-160.2 5.5,-160.2 5.5,-154.2 11.5,-148.2 17.5,-148.2 17.5,-148.2 83.35,-148.2 83.35,-148.2 89.35,-148.2 95.35,-154.2 95.35,-160.2 95.35,-160.2 95.35,-199.8 95.35,-199.8 95.35,-205.8 89.35,-211.8 83.35,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"22.67\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">initial_df</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.spend -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M95.83,-180C103.23,-180 111.05,-180 118.87,-180\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"118.76,-183.5 128.76,-180 118.76,-176.5 118.76,-183.5\"/>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M86.16,-147.78C128.31,-110.59 203.12,-50.53 278.45,-19 322.97,-0.37 337.11,0 385.38,0 385.38,0 385.38,0 620.23,0 779.04,0 954.76,-68.65 1051.83,-113.07\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1050.2,-116.17 1060.75,-117.19 1053.14,-109.82 1050.2,-116.17\"/>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.signups -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M88.9,-212.24C91.09,-214.18 93.25,-216.11 95.35,-218 111.43,-232.49 128.83,-248.69 144.03,-263.03\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"141.46,-265.42 151.13,-269.74 146.27,-260.33 141.46,-265.42\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_mean&#45;&gt;final_df.spend_zero_mean -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>final_df.spend_mean&#45;&gt;final_df.spend_zero_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M464.89,-80.15C480,-84.07 496.09,-88.26 511.94,-92.38\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"510.85,-95.71 521.4,-94.84 512.61,-88.93 510.85,-95.71\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_std_dev&#45;&gt;final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>final_df.spend_std_dev&#45;&gt;final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M472.62,-175.21C538.78,-171.45 632.79,-166.03 715.15,-161 720.86,-160.65 726.67,-160.29 732.54,-159.93\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"732.62,-163.43 742.38,-159.32 732.18,-156.44 732.62,-163.43\"/>\n",
       "</g>\n",
       "<!-- config -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>config</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"71.42,-266 23.42,-266 23.42,-230 77.42,-230 77.42,-260 71.42,-266\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"71.42,-266 71.42,-260\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"77.42,-260 71.42,-260\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-242.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">config</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-320.3C72.85,-320.3 28,-320.3 28,-320.3 22,-320.3 16,-314.3 16,-308.3 16,-308.3 16,-295.7 16,-295.7 16,-289.7 22,-283.7 28,-283.7 28,-283.7 72.85,-283.7 72.85,-283.7 78.85,-283.7 84.85,-289.7 84.85,-295.7 84.85,-295.7 84.85,-308.3 84.85,-308.3 84.85,-314.3 78.85,-320.3 72.85,-320.3\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-296.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- output -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>output</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M67.97,-375.3C67.97,-375.3 32.87,-375.3 32.87,-375.3 26.87,-375.3 20.87,-369.3 20.87,-363.3 20.87,-363.3 20.87,-350.7 20.87,-350.7 20.87,-344.7 26.87,-338.7 32.87,-338.7 32.87,-338.7 67.97,-338.7 67.97,-338.7 73.97,-338.7 79.97,-344.7 79.97,-350.7 79.97,-350.7 79.97,-363.3 79.97,-363.3 79.97,-369.3 73.97,-375.3 67.97,-375.3\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-351.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">output</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x7fc611267610>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module with_columns_example --builder my_builder --display --execute output_node\n",
    "import pandas as pd\n",
    "from hamilton.plugins.h_pandas import with_columns\n",
    "import my_functions\n",
    "\n",
    "output_columns = [\n",
    "    # \"spend\",\n",
    "    # \"signups\",\n",
    "    \"avg_3wk_spend\",\n",
    "    \"spend_per_signup\",\n",
    "    \"spend_zero_mean_unit_variance\",\n",
    "]\n",
    "\n",
    "def initial_df()->pd.DataFrame:\n",
    "    return pd.DataFrame.from_dict(\n",
    "        { \n",
    "            \"signups\": pd.Series([1, 10, 50, 100, 200, 400]),\n",
    "            \"spend\": pd.Series([10, 10, 20, 40, 40, 50])*1e6,\n",
    "            }\n",
    "            )\n",
    "\n",
    "# the with_columns call\n",
    "@with_columns(\n",
    "    *[my_functions],\n",
    "    columns_to_pass=[\"spend\", \"signups\"], # The columns to select from the dataframe\n",
    "    select=output_columns, # The columns to append to the dataframe\n",
    "    # config_required = [\"a\"]\n",
    ")\n",
    "def final_df(initial_df: pd.DataFrame) -> pd.DataFrame:\n",
    "    return initial_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   signups       spend  avg_3wk_spend  spend_per_signup  \\\n",
      "0        1  10000000.0            NaN        10000000.0   \n",
      "1       10  10000000.0            NaN         1000000.0   \n",
      "2       50  20000000.0      13.333333          400000.0   \n",
      "3      100  40000000.0      23.333333          400000.0   \n",
      "4      200  40000000.0      33.333333          200000.0   \n",
      "5      400  50000000.0      43.333333          125000.0   \n",
      "\n",
      "   spend_zero_mean_unit_variance  \n",
      "0                      -1.064405  \n",
      "1                      -1.064405  \n",
      "2                      -0.483821  \n",
      "3                       0.677349  \n",
      "4                       0.677349  \n",
      "5                       1.257934  \n"
     ]
    },
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.1.2 (20240928.0832)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"1323pt\" height=\"422pt\"\n",
       " viewBox=\"0.00 0.00 1322.70 422.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 418)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-418 1318.7,-418 1318.7,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-222 8,-406 92.85,-406 92.85,-222 8,-222\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-388.7\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- case -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>case</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"75.3,-130 19.55,-130 19.55,-80 81.3,-80 81.3,-124 75.3,-130\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"75.3,-130 75.3,-124\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"81.3,-124 75.3,-124\"/>\n",
       "<text text-anchor=\"start\" x=\"35.42\" y=\"-113.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">case</text>\n",
       "<text text-anchor=\"start\" x=\"27.55\" y=\"-85.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">millions</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>final_df.spend_zero_mean</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M703.15,-151.8C703.15,-151.8 535.3,-151.8 535.3,-151.8 529.3,-151.8 523.3,-145.8 523.3,-139.8 523.3,-139.8 523.3,-100.2 523.3,-100.2 523.3,-94.2 529.3,-88.2 535.3,-88.2 535.3,-88.2 703.15,-88.2 703.15,-88.2 709.15,-88.2 715.15,-94.2 715.15,-100.2 715.15,-100.2 715.15,-139.8 715.15,-139.8 715.15,-145.8 709.15,-151.8 703.15,-151.8\"/>\n",
       "<text text-anchor=\"start\" x=\"534.1\" y=\"-128.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_zero_mean</text>\n",
       "<text text-anchor=\"start\" x=\"600.1\" y=\"-100.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1018.5,-181.8C1018.5,-181.8 756.15,-181.8 756.15,-181.8 750.15,-181.8 744.15,-175.8 744.15,-169.8 744.15,-169.8 744.15,-130.2 744.15,-130.2 744.15,-124.2 750.15,-118.2 756.15,-118.2 756.15,-118.2 1018.5,-118.2 1018.5,-118.2 1024.5,-118.2 1030.5,-124.2 1030.5,-130.2 1030.5,-130.2 1030.5,-169.8 1030.5,-169.8 1030.5,-175.8 1024.5,-181.8 1018.5,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"754.95\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_zero_mean_unit_variance</text>\n",
       "<text text-anchor=\"start\" x=\"868.2\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean&#45;&gt;final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>final_df.spend_zero_mean&#45;&gt;final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M715.54,-130.75C721.18,-131.38 726.91,-132.03 732.69,-132.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"732.04,-136.13 742.37,-133.77 732.83,-129.17 732.04,-136.13\"/>\n",
       "</g>\n",
       "<!-- final_df -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>final_df</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1302.7,-181.8C1302.7,-181.8 1236.85,-181.8 1236.85,-181.8 1230.85,-181.8 1224.85,-175.8 1224.85,-169.8 1224.85,-169.8 1224.85,-130.2 1224.85,-130.2 1224.85,-124.2 1230.85,-118.2 1236.85,-118.2 1236.85,-118.2 1302.7,-118.2 1302.7,-118.2 1308.7,-118.2 1314.7,-124.2 1314.7,-130.2 1314.7,-130.2 1314.7,-169.8 1314.7,-169.8 1314.7,-175.8 1308.7,-181.8 1302.7,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"1245.78\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df</text>\n",
       "<text text-anchor=\"start\" x=\"1235.65\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- final_df.spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>final_df.spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M231.45,-211.8C231.45,-211.8 142.35,-211.8 142.35,-211.8 136.35,-211.8 130.35,-205.8 130.35,-199.8 130.35,-199.8 130.35,-160.2 130.35,-160.2 130.35,-154.2 136.35,-148.2 142.35,-148.2 142.35,-148.2 231.45,-148.2 231.45,-148.2 237.45,-148.2 243.45,-154.2 243.45,-160.2 243.45,-160.2 243.45,-199.8 243.45,-199.8 243.45,-205.8 237.45,-211.8 231.45,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"141.15\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend</text>\n",
       "<text text-anchor=\"start\" x=\"167.77\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_zero_mean -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_zero_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.75,-150.87C254.98,-146.12 266.89,-141.84 278.45,-139 355.09,-120.2 444.25,-115.85 512,-115.98\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"511.58,-119.48 521.6,-116.04 511.62,-112.48 511.58,-119.48\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_per_signup -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>final_df.spend_per_signup</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M471.05,-375.8C471.05,-375.8 301.7,-375.8 301.7,-375.8 295.7,-375.8 289.7,-369.8 289.7,-363.8 289.7,-363.8 289.7,-324.2 289.7,-324.2 289.7,-318.2 295.7,-312.2 301.7,-312.2 301.7,-312.2 471.05,-312.2 471.05,-312.2 477.05,-312.2 483.05,-318.2 483.05,-324.2 483.05,-324.2 483.05,-363.8 483.05,-363.8 483.05,-369.8 477.05,-375.8 471.05,-375.8\"/>\n",
       "<text text-anchor=\"start\" x=\"300.5\" y=\"-352.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_per_signup</text>\n",
       "<text text-anchor=\"start\" x=\"367.25\" y=\"-324.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_per_signup -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_per_signup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M212.38,-212.17C223.75,-227.23 237.39,-245.46 249.45,-262 262.6,-280.04 260.83,-289.3 278.45,-303 279.58,-303.87 280.72,-304.73 281.89,-305.57\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"279.62,-308.27 289.89,-310.87 283.49,-302.43 279.62,-308.27\"/>\n",
       "</g>\n",
       "<!-- final_df.avg_3wk_spend -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>final_df.avg_3wk_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M482.3,-293.8C482.3,-293.8 290.45,-293.8 290.45,-293.8 284.45,-293.8 278.45,-287.8 278.45,-281.8 278.45,-281.8 278.45,-242.2 278.45,-242.2 278.45,-236.2 284.45,-230.2 290.45,-230.2 290.45,-230.2 482.3,-230.2 482.3,-230.2 488.3,-230.2 494.3,-236.2 494.3,-242.2 494.3,-242.2 494.3,-281.8 494.3,-281.8 494.3,-287.8 488.3,-293.8 482.3,-293.8\"/>\n",
       "<text text-anchor=\"start\" x=\"289.25\" y=\"-270.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.avg_3wk_spend: case</text>\n",
       "<text text-anchor=\"start\" x=\"367.25\" y=\"-242.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.avg_3wk_spend -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.avg_3wk_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.71,-205.89C255.14,-211.02 267.14,-216.28 278.45,-221 282.04,-222.5 285.72,-224.01 289.43,-225.52\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"288,-228.72 298.58,-229.21 290.61,-222.23 288,-228.72\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_mean -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>final_df.spend_mean</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M452.68,-91.8C452.68,-91.8 320.07,-91.8 320.07,-91.8 314.07,-91.8 308.07,-85.8 308.07,-79.8 308.07,-79.8 308.07,-40.2 308.07,-40.2 308.07,-34.2 314.07,-28.2 320.07,-28.2 320.07,-28.2 452.68,-28.2 452.68,-28.2 458.68,-28.2 464.68,-34.2 464.68,-40.2 464.68,-40.2 464.68,-79.8 464.68,-79.8 464.68,-85.8 458.68,-91.8 452.68,-91.8\"/>\n",
       "<text text-anchor=\"start\" x=\"318.88\" y=\"-68.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_mean</text>\n",
       "<text text-anchor=\"start\" x=\"373.62\" y=\"-40.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">float</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_mean -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M222.31,-148.04C238.55,-134 258.67,-118.01 278.45,-106 284.66,-102.23 291.23,-98.61 297.95,-95.18\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"299.08,-98.52 306.5,-90.95 295.98,-92.24 299.08,-98.52\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_std_dev -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>final_df.spend_std_dev</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M460.18,-211.8C460.18,-211.8 312.57,-211.8 312.57,-211.8 306.57,-211.8 300.57,-205.8 300.57,-199.8 300.57,-199.8 300.57,-160.2 300.57,-160.2 300.57,-154.2 306.57,-148.2 312.57,-148.2 312.57,-148.2 460.18,-148.2 460.18,-148.2 466.18,-148.2 472.18,-154.2 472.18,-160.2 472.18,-160.2 472.18,-199.8 472.18,-199.8 472.18,-205.8 466.18,-211.8 460.18,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"311.38\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.spend_std_dev</text>\n",
       "<text text-anchor=\"start\" x=\"373.62\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">float</text>\n",
       "</g>\n",
       "<!-- final_df.spend&#45;&gt;final_df.spend_std_dev -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>final_df.spend&#45;&gt;final_df.spend_std_dev</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M243.7,-180C257.83,-180 273.42,-180 288.94,-180\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"288.69,-183.5 298.69,-180 288.69,-176.5 288.69,-183.5\"/>\n",
       "</g>\n",
       "<!-- final_df.__append -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>final_df.__append</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1183.85,-181.8C1183.85,-181.8 1071.5,-181.8 1071.5,-181.8 1065.5,-181.8 1059.5,-175.8 1059.5,-169.8 1059.5,-169.8 1059.5,-130.2 1059.5,-130.2 1059.5,-124.2 1065.5,-118.2 1071.5,-118.2 1071.5,-118.2 1183.85,-118.2 1183.85,-118.2 1189.85,-118.2 1195.85,-124.2 1195.85,-130.2 1195.85,-130.2 1195.85,-169.8 1195.85,-169.8 1195.85,-175.8 1189.85,-181.8 1183.85,-181.8\"/>\n",
       "<text text-anchor=\"start\" x=\"1070.3\" y=\"-158.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.__append</text>\n",
       "<text text-anchor=\"start\" x=\"1093.55\" y=\"-130.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- final_df.spend_per_signup&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>final_df.spend_per_signup&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M483.43,-345.54C524.91,-345.8 573.97,-345.59 618.23,-344\"/>\n",
       "</g>\n",
       "<!-- final_df.avg_3wk_spend&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>final_df.avg_3wk_spend&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M471.59,-294.24C531.09,-316.62 602.89,-342.66 618.23,-344\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M620.23,-344C795.12,-359.28 983.91,-249.39 1073.58,-188.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1075.46,-191.51 1081.73,-182.96 1071.5,-185.73 1075.46,-191.51\"/>\n",
       "</g>\n",
       "<!-- final_df.__append&#45;&gt;final_df -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>final_df.__append&#45;&gt;final_df</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M1196.26,-150C1202,-150 1207.75,-150 1213.38,-150\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1213.17,-153.5 1223.17,-150 1213.17,-146.5 1213.17,-153.5\"/>\n",
       "</g>\n",
       "<!-- final_df.signups -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>final_df.signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M237.45,-334.8C237.45,-334.8 136.35,-334.8 136.35,-334.8 130.35,-334.8 124.35,-328.8 124.35,-322.8 124.35,-322.8 124.35,-283.2 124.35,-283.2 124.35,-277.2 130.35,-271.2 136.35,-271.2 136.35,-271.2 237.45,-271.2 237.45,-271.2 243.45,-271.2 249.45,-277.2 249.45,-283.2 249.45,-283.2 249.45,-322.8 249.45,-322.8 249.45,-328.8 243.45,-334.8 237.45,-334.8\"/>\n",
       "<text text-anchor=\"start\" x=\"135.15\" y=\"-311.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">final_df.signups</text>\n",
       "<text text-anchor=\"start\" x=\"167.77\" y=\"-283.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- final_df.signups&#45;&gt;final_df.spend_per_signup -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>final_df.signups&#45;&gt;final_df.spend_per_signup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.84,-315.86C258.96,-317.75 268.57,-319.75 278.29,-321.77\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"277.31,-325.14 287.81,-323.74 278.73,-318.28 277.31,-325.14\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_zero_mean_unit_variance&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>final_df.spend_zero_mean_unit_variance&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M1030.76,-150C1036.54,-150 1042.25,-150 1047.83,-150\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1047.55,-153.5 1057.55,-150 1047.55,-146.5 1047.55,-153.5\"/>\n",
       "</g>\n",
       "<!-- initial_df -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>initial_df</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-211.8C83.35,-211.8 17.5,-211.8 17.5,-211.8 11.5,-211.8 5.5,-205.8 5.5,-199.8 5.5,-199.8 5.5,-160.2 5.5,-160.2 5.5,-154.2 11.5,-148.2 17.5,-148.2 17.5,-148.2 83.35,-148.2 83.35,-148.2 89.35,-148.2 95.35,-154.2 95.35,-160.2 95.35,-160.2 95.35,-199.8 95.35,-199.8 95.35,-205.8 89.35,-211.8 83.35,-211.8\"/>\n",
       "<text text-anchor=\"start\" x=\"22.67\" y=\"-188.7\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">initial_df</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-160.7\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.spend -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M95.83,-180C103.23,-180 111.05,-180 118.87,-180\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"118.76,-183.5 128.76,-180 118.76,-176.5 118.76,-183.5\"/>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.__append -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.__append</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M86.16,-147.78C128.31,-110.59 203.12,-50.53 278.45,-19 322.97,-0.37 337.11,0 385.38,0 385.38,0 385.38,0 620.23,0 779.04,0 954.76,-68.65 1051.83,-113.07\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1050.2,-116.17 1060.75,-117.19 1053.14,-109.82 1050.2,-116.17\"/>\n",
       "</g>\n",
       "<!-- initial_df&#45;&gt;final_df.signups -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>initial_df&#45;&gt;final_df.signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M88.9,-212.24C91.09,-214.18 93.25,-216.11 95.35,-218 111.43,-232.49 128.83,-248.69 144.03,-263.03\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"141.46,-265.42 151.13,-269.74 146.27,-260.33 141.46,-265.42\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_mean&#45;&gt;final_df.spend_zero_mean -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>final_df.spend_mean&#45;&gt;final_df.spend_zero_mean</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M464.89,-80.15C480,-84.07 496.09,-88.26 511.94,-92.38\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"510.85,-95.71 521.4,-94.84 512.61,-88.93 510.85,-95.71\"/>\n",
       "</g>\n",
       "<!-- final_df.spend_std_dev&#45;&gt;final_df.spend_zero_mean_unit_variance -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>final_df.spend_std_dev&#45;&gt;final_df.spend_zero_mean_unit_variance</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M472.62,-175.21C538.78,-171.45 632.79,-166.03 715.15,-161 720.86,-160.65 726.67,-160.29 732.54,-159.93\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"732.62,-163.43 742.38,-159.32 732.18,-156.44 732.62,-163.43\"/>\n",
       "</g>\n",
       "<!-- config -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>config</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"71.42,-266 23.42,-266 23.42,-230 77.42,-230 77.42,-260 71.42,-266\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"71.42,-266 71.42,-260\"/>\n",
       "<polyline fill=\"none\" stroke=\"black\" points=\"77.42,-260 71.42,-260\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-242.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">config</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-320.3C72.85,-320.3 28,-320.3 28,-320.3 22,-320.3 16,-314.3 16,-308.3 16,-308.3 16,-295.7 16,-295.7 16,-289.7 22,-283.7 28,-283.7 28,-283.7 72.85,-283.7 72.85,-283.7 78.85,-283.7 84.85,-289.7 84.85,-295.7 84.85,-295.7 84.85,-308.3 84.85,-308.3 84.85,-314.3 78.85,-320.3 72.85,-320.3\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-296.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- output -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>output</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M67.97,-375.3C67.97,-375.3 32.87,-375.3 32.87,-375.3 26.87,-375.3 20.87,-369.3 20.87,-363.3 20.87,-363.3 20.87,-350.7 20.87,-350.7 20.87,-344.7 26.87,-338.7 32.87,-338.7 32.87,-338.7 67.97,-338.7 67.97,-338.7 73.97,-338.7 79.97,-344.7 79.97,-350.7 79.97,-350.7 79.97,-363.3 79.97,-363.3 79.97,-369.3 73.97,-375.3 67.97,-375.3\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-351.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">output</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x7fc61129fca0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import with_columns_example\n",
    "dr = driver.Builder().with_modules(my_functions, with_columns_example).with_config({\"case\":\"millions\"}).build()\n",
    "print(dr.execute(final_vars=[\"final_df\"])[\"final_df\"])\n",
    "dr.visualize_execution(final_vars=[\"final_df\"])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# We can also run it async"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "%reload_ext hamilton.plugins.jupyter_magic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cell_to_module with_columns_async\n",
    "\n",
    "import asyncio\n",
    "import pandas as pd\n",
    "from hamilton.plugins.h_pandas import with_columns\n",
    "\n",
    "async def data_input() -> pd.DataFrame:\n",
    "    await asyncio.sleep(0.0001)\n",
    "    return pd.DataFrame({\n",
    "        \"a\": [1, 2, 3],\n",
    "        \"b\": [4, 5, 6],\n",
    "        \"c\": [7, 8, 9]\n",
    "    })\n",
    "\n",
    "\n",
    "async def multiply_a(a: pd.Series) -> pd.Series:\n",
    "    await asyncio.sleep(0.0001)\n",
    "    return a * 10\n",
    "\n",
    "\n",
    "async def mean_b(b: pd.Series) -> pd.Series:\n",
    "    await asyncio.sleep(5)\n",
    "    return b.mean()\n",
    "\n",
    "async def a_plus_b(a: pd.Series, b: pd.Series) -> pd.Series:\n",
    "    await asyncio.sleep(1)\n",
    "    return a + b\n",
    "\n",
    "async def multiply_a_plus_mean_b(multiply_a: pd.Series, mean_b: pd.Series) -> pd.Series:\n",
    "    await asyncio.sleep(0.0001)\n",
    "    return multiply_a + mean_b\n",
    "\n",
    "\n",
    "@with_columns(\n",
    "        multiply_a,mean_b,a_plus_b, multiply_a_plus_mean_b,\n",
    "        columns_to_pass=[\"a\", \"b\"]\n",
    ")\n",
    "def final_df(data_input: pd.DataFrame) -> pd.DataFrame:\n",
    "    return data_input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a  b  c  multiply_a  mean_b  a_plus_b  multiply_a_plus_mean_b\n",
      "0  1  4  7          10     5.0         5                    15.0\n",
      "1  2  5  8          20     5.0         7                    25.0\n",
      "2  3  6  9          30     5.0         9                    35.0\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from hamilton import async_driver\n",
    "import with_columns_async\n",
    "\n",
    "async def main():\n",
    "    await asyncio.sleep(2)\n",
    "    dr = (await async_driver.Builder()\n",
    "            .with_modules(with_columns_async)\n",
    "            .with_config({\"case\":\"millions\"})\n",
    "            .build())\n",
    "    results = await dr.execute([\"final_df\"])\n",
    "    print(results[\"final_df\"])\n",
    "\n",
    "await main()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "hamilton",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
